/**
 * 实现项目中的一些琐碎功能
 * 1.日志宏
 * 2.json序列化和反序列化
 * 3.uuid的生成
 */

#pragma once

#include <cstdio>
#include <ctime>
#include <iostream>
#include <string>
#include <memory>
#include <random>
#include <sstream>
#include <atomic>
#include <iomanip>
#include <sstream>
#include <jsoncpp/json/json.h>

namespace rpc
{
    #define LDUG 0
    #define LIFO 1
    #define LERR 2
    #define DEFAULT LDUG

    // 宏只能卸载一行，写成多行需要使用 \ 对末尾的 \n 进行换行
    #define LOG(level, format, ...) {\
        if(level >= DEFAULT)\
        {\
            time_t t = time(NULL);\
            struct tm* tm_ptr = localtime(&t);\
            char time_buffer[32] = {0};\
            strftime(time_buffer, 31, "%m-%d-%T", tm_ptr);\
            fprintf(stdout, "[%s][%s:%d] " format "\n", time_buffer, __FILE__, __LINE__, ##__VA_ARGS__);\
        }\
    }

    #define DLOG(format, ...) LOG(LDUG, format, ##__VA_ARGS__);
    #define ILOG(format, ...) LOG(LIFO, format, ##__VA_ARGS__);
    #define ELOG(format, ...) LOG(LERR, format, ##__VA_ARGS__);

    class JSON
    {
    public:
        static bool serialize(const Json::Value& jsonValue, std::string& jsonStr)
        {
            Json::StreamWriterBuilder swb;
            std::unique_ptr<Json::StreamWriter> swPtr(swb.newStreamWriter());

            std::stringstream ss;
            if(swPtr->write(jsonValue, &ss) != 0)
            {
                std::cout << "序列化失败" << std::endl;
                return false;
            }
            else
            {
                std::cout << "序列化成功" << std::endl;
                jsonStr = ss.str();
            }

            return true;
        }   

        static bool unserialize(const std::string& jsonStr, Json::Value& jsonValue)
        {
            Json::CharReaderBuilder crb;
            std::string errorMsg;

            std::unique_ptr<Json::CharReader> crPtr(crb.newCharReader());
            
            bool ret = crPtr->parse(jsonStr.c_str(), jsonStr.c_str()+jsonStr.size(), &jsonValue, &errorMsg);
            
            if(ret == false)
            {
                std::cout << "反序列化失败" << std::endl;
                std::cout << "失败原因: " << errorMsg << std::endl;
                return false;
            }
            else
            {
                std::cout << "反序列化成功" << std::endl;
            }

            return true;
        }
    };

    class UUID
    {
    public:
        static std::string uuid()
        {
            std::stringstream ss;
            // 1.构造一个机器随机数对象
            std::random_device rd;
            // 2.以机器随机数为种子构造伪随机数对象
            std::mt19937 generator(rd());
            // 3.构造限定数据范围的对象
            std::uniform_int_distribution<int> distribution(0, 255);
            // 4.生成8个随机数，按照特定格式组织成16进制数字字符的字符串
            for(int i = 0; i < 8; i++)
            {
                if(i == 4 || i == 6) ss << "-";
                ss << std::setw(2) << std::setfill('0') << std::hex << distribution(generator);
            }
            ss << "-";

            // 5.定义一个8字节序号，逐字节组织成16进制数字字符的字符串
            static std::atomic<size_t> seq(1);
            size_t cur = seq.fetch_add(1);
            for(int i = 7; i >= 0; i--)
            {
                if(i == 5) ss << "-";
                
                ss << std::setw(2) << std::setfill('0') << std::hex << ((cur >> (i*8))&0xFF);
            }

            return ss.str();
        }
    };
}